/**
 * Created on May 18, 2007
 */
package jvs.vfs.sound.sampled.spi;

import java.util.ArrayList;
import java.util.List;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioFormat.Encoding;
import javax.sound.sampled.spi.FormatConversionProvider;

/**
 * @author qiangli
 * 
 */
public class BasicFormatConversionProvider extends FormatConversionProvider {

	private static FormatConversionProvider codecs[] = null;

	public static void init(List<FormatConversionProvider> converters) {
		codecs = (FormatConversionProvider[]) converters.toArray(new FormatConversionProvider[0]);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.sound.sampled.spi.FormatConversionProvider#getAudioInputStream(javax.sound.sampled.AudioFormat,
	 *      javax.sound.sampled.AudioInputStream)
	 */
	public AudioInputStream getAudioInputStream(AudioFormat targetFormat,
			AudioInputStream sourceStream) {
		if (sourceStream.getFormat().matches(targetFormat)) {
			return sourceStream;
		}

		for (int i = 0; i < codecs.length; i++) {

			if (codecs[i].isConversionSupported(targetFormat, sourceStream
					.getFormat())) {
				return codecs[i]
						.getAudioInputStream(targetFormat, sourceStream);
			}
		}

		throw new IllegalArgumentException("Unsupported conversion: "
				+ targetFormat + " from " + sourceStream.getFormat());

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.sound.sampled.spi.FormatConversionProvider#getAudioInputStream(javax.sound.sampled.AudioFormat.Encoding,
	 *      javax.sound.sampled.AudioInputStream)
	 */
	public AudioInputStream getAudioInputStream(Encoding targetEncoding,
			AudioInputStream sourceStream) {

		for (int i = 0; i < codecs.length; i++) {
			if (codecs[i].isConversionSupported(targetEncoding, sourceStream
					.getFormat())) {
				return codecs[i].getAudioInputStream(targetEncoding,
						sourceStream);
			}
		}

		throw new IllegalArgumentException("Unsupported conversion: "
				+ targetEncoding + " from " + sourceStream.getFormat());

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.sound.sampled.spi.FormatConversionProvider#getSourceEncodings()
	 */
	public Encoding[] getSourceEncodings() {
		List<Encoding> encodings = new ArrayList<Encoding>();
		for (int i = 0; i < codecs.length; i++) {
			AudioFormat.Encoding encs[] = codecs[i].getSourceEncodings();
			for (int j = 0; j < encs.length; j++) {
				encodings.add(encs[j]);
			}

		}
		return (Encoding[]) encodings.toArray(new Encoding[0]);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.sound.sampled.spi.FormatConversionProvider#getTargetEncodings()
	 */
	public Encoding[] getTargetEncodings() {
		List<Encoding> encodings = new ArrayList<Encoding>();
		for (int i = 0; i < codecs.length; i++) {
			AudioFormat.Encoding encs[] = codecs[i].getTargetEncodings();
			for (int j = 0; j < encs.length; j++) {
				encodings.add(encs[j]);
			}

		}
		return (Encoding[]) encodings.toArray(new Encoding[0]);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.sound.sampled.spi.FormatConversionProvider#getTargetEncodings(javax.sound.sampled.AudioFormat)
	 */
	public Encoding[] getTargetEncodings(AudioFormat sourceFormat) {
		List<Encoding> encodings = new ArrayList<Encoding>();
		for (int i = 0; i < codecs.length; i++) {
			AudioFormat.Encoding encs[] = codecs[i]
					.getTargetEncodings(sourceFormat);
			for (int j = 0; j < encs.length; j++) {
				encodings.add(encs[j]);
			}

		}
		return (Encoding[]) encodings.toArray(new Encoding[0]);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.sound.sampled.spi.FormatConversionProvider#getTargetFormats(javax.sound.sampled.AudioFormat.Encoding,
	 *      javax.sound.sampled.AudioFormat)
	 */
	public AudioFormat[] getTargetFormats(Encoding targetEncoding,
			AudioFormat sourceFormat) {
		List<AudioFormat> fmts = new ArrayList<AudioFormat>();
		for (int i = 0; i < codecs.length; i++) {
			AudioFormat fmt[] = codecs[i].getTargetFormats(targetEncoding,
					sourceFormat);
			for (int j = 0; j < fmt.length; j++) {
				fmts.add(fmt[j]);
			}

		}
		return (AudioFormat[]) fmts.toArray(new AudioFormat[0]);
	}

	public boolean isConversionSupported(AudioFormat targetFormat,
			AudioFormat sourceFormat) {
		for (int i = 0; i < codecs.length; i++) {
			if (codecs[i].isConversionSupported(targetFormat, sourceFormat)) {
				return true;
			}
		}
		return false;
	}

	public boolean isConversionSupported(Encoding targetEncoding,
			AudioFormat sourceFormat) {

		for (int i = 0; i < codecs.length; i++) {
			if (codecs[i].isConversionSupported(targetEncoding, sourceFormat)) {
				return true;
			}
		}
		return false;
	}

	public boolean isSourceEncodingSupported(Encoding sourceEncoding) {
		for (int i = 0; i < codecs.length; i++) {
			if (codecs[i].isSourceEncodingSupported(sourceEncoding)) {
				return true;
			}
		}
		return false;
	}

	public boolean isTargetEncodingSupported(Encoding targetEncoding) {
		for (int i = 0; i < codecs.length; i++) {
			if (codecs[i].isTargetEncodingSupported(targetEncoding)) {
				return true;
			}
		}
		return false;
	}

}
